大家好,鐵人賽第三天,我們正式進入核心領域!
昨天,我們建立了宏觀的認知,知道了 MCP 是一套為了解決 AI 服務整合亂象而生的「通用語言」。今天,我們要從「使用者」的角色,轉換為「架構師」,戴上放大鏡,先認識參與這場對話的 三大核心角色,再深入剖析他們之間溝通時所遵循的 雙層架構。
在 MCP 的世界裡,所有的互動都圍繞著一個主從式架構 (Client-Server Architecture) 展開。官方文件定義了三個關鍵的參與者:
它們之間的關係可以用下面這張圖清晰地表達:
核心概念: 一個 Host (主應用) 透過內部多個 Client,分別與多個 Server 建立一對一的專線,從而彙整來自四面八方的「情境」與「能力」。
而同一個 MCP server 可以連接多個 MCP client,如下圖
了解了三大角色之後,我們來看看它們之間是如何溝通的。MCP 協議由兩個層次構成,它們像同心圓一樣,各司其職:
這種分層設計的好處是關注點分離 (Separation of Concerns)。資料層不用關心訊息是透過網路 (HTTP) 還是本機 (Stdio) 傳輸,它只專注於定義一套標準的 JSON-RPC 訊息格式。
MCP 目前支援兩種主要的「運輸工具」:
這是我們今天的絕對主角。資料層採用了廣泛使用的 JSON-RPC 2.0 協議,來定義所有 Client 與 Server 之間的互動。
它包含三大核心職責:
讓我們聚焦在資料層,看看一次 MCP 通訊是如何開始的。
MCP 是一個有狀態 (Stateful) 的協議。這意味著在正式交換資料前,Client 和 Server 必須先進行一個「握手」儀式,這個過程被稱為生命週期管理,其核心就是 initialize
(初始化) 請求。
initialize
請求:能力協商的開始當一個 MCP Client 連接上一個 MCP Server 時,它會發送第一個請求,方法名為 initialize
。
客戶端發送的 initialize
請求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-08-29",
"capabilities": {
"elicitation": {}
},
"clientInfo": {
"name": "example-client",
"version": "1.0.0"
}
}
}
這個請求就像是在說:「你好,我是某某客戶端,我支援『使用者互動』(elicitation
) 這個功能,我使用的協議版本是這個,我們來對一下規格吧!」
伺服器回傳的 initialize
回應:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-08-29",
"capabilities": {
"tools": {
"listChanged": true
},
"resources": {}
},
"serverInfo": {
"name": "example-server",
"version": "1.0.0"
}
}
}
伺服器回應說:「你好,規格確認無誤。我能提供『工具』(tools
) 和『資源』(resources
) 兩種服務,而且我的工具列表是會動態更新的 ("listChanged": true
)。」
這個 initialize
握手過程,完美地取代了傳統 API 中零散的 Header 或 Metadata。它在一次請求中,就完成了版本協商、能力宣告、身份交換三件大事,為後續的通訊鋪平了道路。
初始化完成後,就進入了真正的「酬載 (Payload)」交換階段。在 MCP 的世界裡,酬載的核心內容被定義為三種伺服器原語 (Server Primitives)。
Primitives (原語) 是 MCP 中最重要的概念,它們定義了伺服器可以向 AI 應用程式提供哪些類型的「情境」和「能力」。
這三種核心原語分別是:
讓我們接續上面的 initialize
流程,看看客戶端如何使用 tools
這個原語。
1. 發現工具 (tools/list
): 客戶端想知道伺服器上有哪些工具可用。
// Request
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
伺服器會回傳一個工具列表,每個工具都包含詳細的描述和輸入格式 (inputSchema
)。
2. 執行工具 (tools/call
): 客戶端決定使用其中一個名為 weather_current
的工具。
// Request
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "weather_current",
"arguments": {
"location": "San Francisco",
"units": "imperial"
}
}
}
// Response
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "Current weather in San Francisco: 68°F, partly cloudy..."
}
]
}
}
可以看到,params
物件就是這次請求的酬載 (Payload),它嚴格遵循了 tools/list
中定義的 inputSchema
。而 result
中的 content
陣列,就是伺服器回傳的酬載。
今天我們深入了 MCP 的核心,從一份權威的官方文件中,我們學到了:
initialize
握手,用來交換版本和能力。明天,我們終於要親自動手了!我們將請出強大的低程式碼自動化工具 n8n,實際搭建我們的環境,準備發送出第一個真正的 MCP 請求!